//== GAIA ============================================================================

//== BEGINNING OF CODE ===============================================================

#include "sagittarius/core/SagittariusCore.h"

//GAIA headers:
#include "sagittarius/unicode/CUnicode.h"

#include <stdio.h>
#include <time.h>
#include <malloc.h>
#include <string.h>

///CompareArg
//Compares the two strings
//Will fail if lengths do not match
int CompareArg(const char* arg, const char* cmp)
{
    while(*arg == *cmp && *arg != '\0' && *cmp != '\0')
    {
        ++arg;
        ++cmp;
    }
    if(*arg == *cmp)
        return 1;
    else
        return 0;
}
///CompareArg_Short
//Compares two strings until null char is found
//Terminates at null char, returning 1 if strings match
//up to first occurrence of null char
int CompareArg_Short(const char* arg, const char* cmp)
{
    while(1) {
        if(*arg == '\0' || *cmp == '\0')
            return 1;
        if(*arg != *cmp)
            break;
        ++arg;
        ++cmp;
    }
    return 0;
}

int IsUIntegerString(const char* arg)
{
    //ASCII:
    //0x30 = '0'
    //0x39 = '9'
    while(0x30 <= *arg && *arg <= 0x39) {
        ++arg;
    }
    if(*arg == '\0')
        return 1;
    else
        return 0;
}

unsigned int String2UInt(const char* arg)
{
    unsigned int result=0;
    //ASCII:
    //0x30 = '0'
    //0x39 = '9'
    while(0x30 <= *arg && *arg <= 0x39)
    {
        result *= 10;
        result += (unsigned int)(*arg-0x30);
        ++arg;
    }
    assert(*arg == '\0');
    return result;
}

int main(int argc, char* argv[])
{
    int result, i;
    clock_t t_start, t_finish;
    int do_print=0;
	char* buf;
	size_t bytes_read;
	UnicodeCChar* ubuf;
    
    size_t size=0;
    
    FILE* file=NULL;
    
    assert(argc >= 3);
    
    for(i=1; i<argc-1; ++i)
    {
        //size specifier
        if(CompareArg_Short(argv[i], "--size"))
        {
            if(argv[i][6] != '=') {
                fprintf(stderr, "Error: expected \"=\" after \"--size\", found instead \"%c\"\n", argv[i][6]);
                return -1;
            }
            if(!IsUIntegerString(argv[i]+7)) {
                fprintf(stderr, "Error: expected unsigned integer after \"--size=\"\n");
                return -1;
            }
            else {
                //is an integer string
                size = String2UInt(argv[i]+7);
            }
        }
        //print converted buffer
        else if(CompareArg(argv[i], "--print"))
            do_print = 1;
        else {
            //not recognized
            fprintf(stderr, "Error: unrecognized token on command line: %s\n", argv[i]);
            return -1;
        }
    }
    
    //size of UnicodeCChar:
    fprintf(stderr, "Size of UnicodeCChar is %lu\n", sizeof(UnicodeCChar));
    
    //file size as given on the command line
    fprintf(stderr, "Specified file is %s\n", argv[argc-1]);
    fprintf(stderr, "Specified file size is %lu\n", size);
    
    /*open*/
    assert(size > 0);
    file = fopen(argv[argc-1], "r");
    if(!file)
    {
        assert(0 && "Failed to open file");
        return -1;
    }
    
    //allocated buffer
    assert(sizeof(char) == 1 && "char must be one byte wide");
    buf=(char*)malloc(size+1); //one extra byte for null char
    assert(buf && "Failed to allocate buffer");
    //read the whole file at once
    bytes_read = fread(buf, 1, size, file);
    assert(bytes_read == size && "Failed to read whole file (wrong size specified?)");
    //trip EOF indicator
    fgetc(file);
    assert(feof(file) && "EOF Expected");
    buf[size] = 0x00; //terminating null char
    
    /*close*/
    fclose(file);
    
    //create buffer for unicode values
    ubuf = (UnicodeCChar*)malloc((size+1)*sizeof(UnicodeCChar));
    assert(ubuf && "Unable to allocate memory");
    
    #define PASSES 1000
    t_start = clock(); //clock
    for(i=0;i<PASSES;++i)
    {
        memset(ubuf, 0x00, size);
        //convert
        result = UTF8_ConvertBuffer(buf, ubuf);
        if(result < 0)
        {
            fprintf(stderr, "Failed to convert buffer, routine returned with code %d\n", result);
            free(ubuf);
            return -1;
        }
    }
    t_finish = clock(); //clock
    
    //print converted buffer
    if(do_print)
        printUnicodeBuf(ubuf);
    printf("\nRoutine returned with code %d\n", result);
    
    //free buffer
    free(buf);
    free(ubuf);
    
    //print benchmark
    printf("Parsing: %.4lf secs\n", (t_finish-t_start)/(double)CLOCKS_PER_SEC);
    
    
    return 0;
}
